package doubanbook

import (
	"gitee.com/1043532278/dll_crawler/collect"
	"go.uber.org/zap"
	"regexp"
	"strconv"
)

var DoubanBookTask = &collect.Task{
	Property: collect.Property{
		Name:     "douban_book_list2",
		WaitTime: 2,
		MaxDepth: 5,
		Cookie:   "_pk_id.100001.3ac3=33f34543516e1028.1728799984.; __yadk_uid=UUEedC1da4Nd2vWugxG1zjwrFFXPVxza; _vwo_uuid_v2=DAD8906EC5FA0B2DEC1788FE20BE695C6|1d21691bd5e8b821011acc9644fd7523; douban-fav-remind=1; _ga=GA1.1.1378402030.1708701027; _ga_RXNMP372GL=GS1.1.1732067523.2.0.1732067523.60.0.0; _vwo_uuid_v2=DE58FA50A2903FEC93DD5C3476C2CDF09|914c478a2a3bd0e4598565c336b102d2; ll=\"118286\"; bid=Se6MyjtTG9g; __utmz=81379588.1745354466.5.5.utmcsr=cn.bing.com|utmccn=(referral)|utmcmd=referral|utmcct=/; __utmc=30149280; viewed=\"1007305_30578908\"; _pk_ref.100001.3ac3=%5B%22%22%2C%22%22%2C1753531573%2C%22https%3A%2F%2Fcn.bing.com%2F%22%5D; __utmc=81379588; dbcl2=\"143826021:KJ8EluSkBwc\"; ck=zh4v; push_doumail_num=0; __utmv=30149280.14382; frodotk_db=\"7e14bb9df61f0e5c7a3e32d9e25d2b14\"; push_noty_num=0; __utmz=30149280.1754152614.23.20.utmcsr=bing|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); __utma=30149280.1378402030.1708701027.1754152614.1754514153.24; __utma=81379588.1836153219.1728799984.1753531573.1754514153.7",
	},
	Rule: collect.RuleTree{
		Root: func() ([]*collect.Request, error) {
			roots := []*collect.Request{
				&collect.Request{
					Priority: 1,
					Url:      "https://book.douban.com",
					Method:   "GET",
					RuleName: "数据tag",
				},
			}
			return roots, nil
		},
		Trunk: map[string]*collect.Rule{
			"数据tag": &collect.Rule{ParseFunc: ParseTag},
			"书籍列表":  &collect.Rule{ParseFunc: ParseBookList},
			"书籍简介": &collect.Rule{
				ItemFields: []string{
					"书名",
					"作者",
					"页数",
					"出版社",
					"得分",
					"价格",
					"简介",
				},
				ParseFunc: ParseBookDetail,
			},
		},
	},
}

const regexpStr = `<a href="([^"]+)" class="tag">([^<]+)</a>`

func ParseTag(ctx *collect.Context) (collect.ParseResult, error) {
	re := regexp.MustCompile(regexpStr)

	matches := re.FindAllSubmatch(ctx.Body, -1)
	result := collect.ParseResult{}

	for _, m := range matches {
		result.Requesrts = append(
			result.Requesrts, &collect.Request{
				Method: "GET",
				Task:   ctx.Req.Task,
				Url:    "https://book.douban.com" + string(m[1]),
				// <a href="/tag/漫画" class="tag">漫画</a>
				Depth:    ctx.Req.Depth + 1,
				RuleName: "书籍列表",
			})
	}

	zap.S().Debugln("parse book tag,count:", len(result.Requesrts))
	// 在添加limit之前，临时减少抓取数量,防止被服务器封禁
	//result.Requesrts = result.Requesrts[:1]
	return result, nil
}

const BooklistRe = `<a.*?href="([^"]+)" title="([^"]+)"`

// <a href="https://book.douban.com/subject/37269363/" title="哲学家的最后一课"> </a>
func ParseBookList(ctx *collect.Context) (collect.ParseResult, error) {
	re := regexp.MustCompile(BooklistRe)
	matches := re.FindAllSubmatch(ctx.Body, -1)
	result := collect.ParseResult{}
	for _, m := range matches {
		req := &collect.Request{
			Priority: 100,
			Method:   "GET",
			Task:     ctx.Req.Task,
			Url:      string(m[1]),
			Depth:    ctx.Req.Depth + 1,
			RuleName: "书籍简介",
		}
		req.TmpData = &collect.Temp{}
		req.TmpData.Set("book_name", string(m[2]))
		result.Requesrts = append(result.Requesrts, req)
	}
	zap.S().Debugln("parse book list,count:", len(result.Requesrts))

	return result, nil
}

var autoRe = regexp.MustCompile(`<span class="pl"> 作者</span>:[\d\D]*?<a.*?>([^<]+)</a>`)
var public = regexp.MustCompile(`<span class="pl">出版社:</span>[\d\D]*?<a.*?>([^<]+)</a>`)
var pageRe = regexp.MustCompile(`<span class="pl">页数:</span> ([^<]+)<br/>`)
var priceRe = regexp.MustCompile(`<span class="pl">定价:</span>([^<]+)<br/>`)
var scoreRe = regexp.MustCompile(`<strong class="ll rating_num " property="v:average">([^<]+)</strong>`)
var intoRe = regexp.MustCompile(`<div class="intro">[\d\D]*?<p>([^<]+)</p></div>`)

func ParseBookDetail(ctx *collect.Context) (collect.ParseResult, error) {
	bookName := ctx.Req.TmpData.Get("book_name")
	page, _ := strconv.Atoi(ExtraString(ctx.Body, pageRe))

	book := map[string]interface{}{
		"书名":  bookName,
		"作者":  ExtraString(ctx.Body, autoRe),
		"页数":  page,
		"出版社": ExtraString(ctx.Body, public),
		"得分":  ExtraString(ctx.Body, scoreRe),
		"价格":  ExtraString(ctx.Body, priceRe),
		"简介":  ExtraString(ctx.Body, intoRe),
	}
	data := ctx.Output(book)

	result := collect.ParseResult{
		Items: []interface{}{data},
	}
	zap.S().Debugln("parse book detail", data)

	return result, nil
}

func ExtraString(contents []byte, re *regexp.Regexp) string {

	match := re.FindSubmatch(contents)

	if len(match) >= 2 {
		return string(match[1])
	} else {
		return ""
	}
}
